package binarytree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

/**
 * @Author: 海琳琦
 * @Date: 2022/2/18 18:04
 * https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
 */
public class PostorderTraversal {

    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode() {
        }

        public TreeNode(int val) {
            this.val = val;
        }

        public TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    /**
     * 非递归后序遍历（与前序遍历和中序遍历套路不太一样，需要分情况）
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.peek();
            //当左孩子遍历完，右孩子为空直接输出根节点 ||当前根节点的前驱节点是其右孩子（即左右均遍历完，输出根节点）
            if (root.right == null || root.right == pre) {
                result.add(root.val);
                pre = root;
                stack.pop();
                root = null;
            }else{
                root = root.right;
            }
        }
        return result;
    }


    /**
     * 非递归后序遍历2  后序遍历顺序 左-右-中 入栈顺序：中-左-右 出栈顺序：中-右-左， 最后翻转结果
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal3(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        if (root != null) {
            stack.push(root);
        }
        while (!stack.isEmpty()) {
            TreeNode pop = stack.pop();
            result.add(pop.val);
            if (pop.left != null) {
                stack.push(pop.left);
            }
            if (pop.right != null) {
                stack.push(pop.right);
            }
        }
        Collections.reverse(result);
        return result;
    }


    /**
     * 递归遍历
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal1(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        postorder(root, result);
        return result;
    }


    private void postorder(TreeNode root, List<Integer> result) {
        if (root != null) {
            postorder(root.left, result);
            result.add(root.val);
            postorder(root.right, result);
        }
    }

    public static void main(String[] args) {

    }
}
